package com.jnzc.ocr.serv.shop.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.collect.Lists;
import com.jnzc.ocr.common.utils.*;
import com.jnzc.ocr.dependencies.serv.mybatis.MybatisServiceImpl;
import com.jnzc.ocr.serv.shop.consts.ShopOrderConsts;
import com.jnzc.ocr.serv.shop.entity.*;
import com.jnzc.ocr.serv.shop.filter.ShopOrderSaleFilter;
import com.jnzc.ocr.serv.shop.helper.ShopOrderHelper;
import com.jnzc.ocr.serv.shop.helper.ShopOrderSaleHelper;
import com.jnzc.ocr.serv.shop.mapper.ShopOrderSaleMapper;
import com.jnzc.ocr.serv.shop.service.*;
import com.jnzc.ocr.serv.shop.vo.ShopMarketingPlanSelectResultVo;
import com.jnzc.ocr.serv.shop.vo.ShopMarketingPlanSelectedVo;
import com.jnzc.ocr.serv.shop.vo.ShopOrderSaleCreateVo;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @author zhangcm
 * @version 1.0, 2017-10-06
 */
@Service
public class ShopOrderSaleServiceImpl extends MybatisServiceImpl<ShopOrderSaleMapper, ShopOrderSale, ShopOrderSaleFilter> implements ShopOrderSaleService {

    @Autowired
    private ShopOrderService shopOrderService;

    @Autowired
    private ShopOrderSaleDetailService shopOrderSaleDetailService;

    @Autowired
    private ShopMemberService shopMemberService;

    @Autowired
    private ShopGoodsService shopGoodsService;

    @Autowired
    private ShopGoodsSkuService shopGoodsSkuService;

    @Autowired
    private ShopMarketingPlanService shopMarketingPlanService;

    @Override
    protected void fillEntityWrapper(EntityWrapper<ShopOrderSale> ew, ShopOrderSaleFilter filter) {
        ShopOrderSale entity = new ShopOrderSale();
        entity.setOrderId(filter.getOrderId());
        ew.setEntity(entity);
    }

    @Override
    public ShopOrderSale find(Long orderId) {
        ShopOrderSaleFilter filter = new ShopOrderSaleFilter();
        filter.setOrderId(orderId);
        return super.findNotNull(filter);
    }

    @Override
    @Transactional
    public ShopOrder create(ShopOrderSaleCreateVo createVo) {
        // 检查
        Long shopId = createVo.getOrder().getShopId();
        ValidateUtils.isId(shopId, "店铺ID");
        ValidateUtils.notNull(createVo.getSale().getSaleWay(), "销售途径");
        ValidateUtils.notEmpty(createVo.getSaleDetailList(), "产品");
        for (ShopOrderSaleDetail param : createVo.getSaleDetailList()) {
            ValidateUtils.isId(param.getProductId(), "产品ID");
            ValidateUtils.inRange(param.getNum(), 1, "数量");
        }
        // 获取销售详情
        List<ShopOrderSaleDetail> saleDetailList = Lists.newArrayList();
        for (ShopOrderSaleDetail saleDetailParam : createVo.getSaleDetailList()) {
            ShopGoods goods = shopGoodsService.find(saleDetailParam.getProductId(), shopId);
            BigDecimal price = goods.getPrice();
            ShopGoodsSku goodsSku = null;
            if(null != saleDetailParam.getSkuId()){
                goodsSku = shopGoodsSkuService.find(saleDetailParam.getSkuId(), saleDetailParam.getProductId(), shopId);
                price = goodsSku.getPrice();
            }
            ShopOrderSaleDetail obj = new ShopOrderSaleDetail();
            obj.setShopId(shopId);
            obj.setProductId(goods.getId());
            obj.setProductName(goods.getName());
            if(null != goodsSku){
                obj.setSkuId(goodsSku.getId());
                obj.setSkuName(goodsSku.getName());
            }
            obj.setProductCategoryId(goods.getCategoryId());
            obj.setPrice(price);
            obj.setSalePrice(price);
            obj.setNum(saleDetailParam.getNum());
            obj.setSaleAmount(BigDecimalUtils.mul(obj.getSalePrice(), obj.getNum()));
            obj.setDiscountAmount(BigDecimal.ZERO);
            saleDetailList.add(obj);
        }
        String orderName = ShopOrderSaleHelper.getOrderName(saleDetailList);
        Integer totalNum = ShopOrderSaleHelper.getTotalNum(saleDetailList);

        ShopOrder order = new ShopOrder();
        order.setShopId(shopId);
        order.setNo(ShopOrderHelper.createNo(shopId));
        order.setName(orderName);
        order.setMemberId(createVo.getOrder().getMemberId());
        if(null != createVo.getOrder().getMemberId()){
            ShopMember member = shopMemberService.find(createVo.getOrder().getMemberId(), shopId);
            order.setMemberName(member.getName());
        }
        order.setType(ShopOrderConsts.TYPE_SALE);
        order.setNum(totalNum);
        order.setUserId(createVo.getOrder().getUserId());
        order.setUserName(createVo.getOrder().getUserName());
        order.setState(ShopOrderConsts.STATE_UNPAY);
        order.setCreateTime(DateUtils.getNow());

        ShopOrderSale sale = new ShopOrderSale();
        sale.setShopId(shopId);
        sale.setSaleWay(createVo.getSale().getSaleWay());

        // 计算营销方案
        calculateMarketing(order, sale, saleDetailList, createVo.getMarketingList(), shopId);

        shopOrderService.insertOne(order);

        sale.setOrderId(order.getId());
        this.insertOne(sale);

        // 保存订单销售详情
        for (ShopOrderSaleDetail obj : saleDetailList) {
            obj.setOrderId(order.getId());
        }
        shopOrderSaleDetailService.insertList(saleDetailList);

        return order;
    }

    private void calculateMarketing(ShopOrder order, ShopOrderSale sale, List<ShopOrderSaleDetail> saleDetailList, List<ShopMarketingPlanSelectedVo> marketingList, Long shopId) {
        List<ShopMarketingPlanSelectResultVo> planList = shopMarketingPlanService.list(marketingList, shopId);
        List<ShopMarketingPlanSelectResultVo> allPlanList = Lists.newArrayList();
        List<ShopMarketingPlanSelectResultVo> categoryPlanList = Lists.newArrayList();
        for (ShopMarketingPlanSelectResultVo plan : planList) {
            if(null == plan.getPlan().getProductCategoryId()) {
                allPlanList.add(plan);
            } else {
                categoryPlanList.add(plan);
            }
        }
        Map<Long, List<ShopOrderSaleDetail>> saleDetailMap = ArrayHandleUtils.parseMapGroup(saleDetailList, "productCategoryId");
        // 产品分类营销方案
        for (ShopMarketingPlanSelectResultVo plan : categoryPlanList) {
            List<ShopOrderSaleDetail> tempList = saleDetailMap.get(plan.getPlan().getProductCategoryId());
            calculateMarketing(tempList, plan);
        }
        // 所有产品分类营销方案
        for (ShopMarketingPlanSelectResultVo plan : allPlanList) {
            calculateMarketing(saleDetailList, plan);
        }

        BigDecimal totalSaleAmount = ShopOrderSaleHelper.getTotalSaleAmount(saleDetailList);
        BigDecimal totalDiscountAmount = ShopOrderSaleHelper.getTotalDiscountAmount(saleDetailList);
        BigDecimal totalAmount = BigDecimalUtils.sub(totalSaleAmount, totalDiscountAmount);

        order.setAmount(totalAmount);
        order.setAddPoint(0);

        sale.setSaleAmount(totalSaleAmount);
        sale.setDiscountAmount(totalDiscountAmount);
    }

    private void calculateMarketing(List<ShopOrderSaleDetail> saleDetailList, ShopMarketingPlanSelectResultVo plan) {
        BusinessUtils.isTrue(CollectionUtils.isNotEmpty(saleDetailList), plan.getPlan().getName() + "营销方案无法在该订单使用");
        BigDecimal totalAmount = ShopOrderSaleHelper.getTotalAmount(saleDetailList);
        BigDecimal planAmount = ShopOrderSaleHelper.getPlanAmount(plan, totalAmount);
        BigDecimal addDiscountAmount = BigDecimal.ZERO;
        for (int i = 0; i < saleDetailList.size() - 1; i++) {
            ShopOrderSaleDetail detail = saleDetailList.get(i);
            BigDecimal tempDiscountAmount = CalculateUtils.div(CalculateUtils.mul(detail.getSalePrice(), planAmount), totalAmount, 2);
            detail.setDiscountAmount(CalculateUtils.add(detail.getDiscountAmount(), tempDiscountAmount));
            addDiscountAmount = addDiscountAmount.add(tempDiscountAmount);
        }
        ShopOrderSaleDetail lastDetail = saleDetailList.get(saleDetailList.size() - 1);
        lastDetail.setDiscountAmount(CalculateUtils.add(lastDetail.getDiscountAmount(), CalculateUtils.sub(planAmount, addDiscountAmount)));
    }
}
